package view;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.util.zip.DataFormatException;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;

import server.FirewallException;
import server.FirewallSession;
import server.NotExpertException;
import server.ReadWriteException;
import server.RulesTableType;

public class RulesAdvancedFrame  extends AbstractRulesFrame
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 9201679036101368799L;

	/* Current shown window */	
	public static RulesAdvancedFrame currentRulesAdvancedFrame = null;

	/* Frame default name */	
	private static String title = null;
	
	public RulesAdvancedFrame(FirewallSession ui) {
		super(ui);
	}

	public static RulesAdvancedFrame getInctance(FirewallSession ui)
	{
		if(currentRulesAdvancedFrame == null)
		{
			currentRulesAdvancedFrame = new RulesAdvancedFrame(ui);
			title = currentRulesAdvancedFrame.getTitle();
		}else{
			RulesAdvancedTable.currentInRulesAdvancedTable.build();
			RulesAdvancedTable.currentOutRulesAdvancedTable.build();
		}
		
		return currentRulesAdvancedFrame;
	}

	/**
	 * The relevant help calling
	 */
	protected void rulesHelp() 
	{
		HelpFrame.currentHelpFrame.ShowDesc(Globals.RULES);	
	}

	/**
	 * Adds buttons for ruleset loading, saving and reseting
	 */
	protected Box getUpRulesButtons() 
	{		
		/* Button for loading */	
		Box buttons = Box.createVerticalBox();
	
		
				
		JButton load = new JButton("Load and Edit..");
		load.setToolTipText("Load the ruleset by user choice");
		
		load.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				RulesetLoadFrame frame = new RulesetLoadFrame();
				frame.setVisible(true);
			}	  
		});
		buttons.add(load);

		/* Button for saving */		
		JButton save = new JButton("Duplicate...     ");
		save.setToolTipText("Duplicate currently working ruleset");
		
		save.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				RulesetSaveFrame frame = new RulesetSaveFrame(UI);
				frame.setVisible(true);
			}	  
		});
		buttons.add(save);		
	
		/* Button for reseting */	
		JButton reset = new JButton("Restore           ");
		reset.setToolTipText("Load current Firewall's ruleset ");
		
		buttons.add(reset);
		reset.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				try {
					Settings.ruleset = UI.getCurrentRuleSet();
					RulesAdvancedTable.currentInRulesAdvancedTable.build();
					RulesAdvancedTable.currentOutRulesAdvancedTable.build();
					RulesAdvancedFrame.currentRulesAdvancedFrame.isCurrentRuleSet(true);
				} catch (RemoteException e1) {
					ErrorFrame.AddError("Failed to reset ruleset :" + e1.getMessage(), new JFrame());
				}
			}	  
		});
		
		
		/* Button for reseting */	
		JButton set = new JButton("Set as Current ");
		set.setToolTipText("Set current ruleset to be current ruleset at firewall");
		set.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				try {
					UI.setRuleSet(Settings.ruleset);
					isCurrentRuleSet(true);
				} catch (RemoteException e1) {
					ErrorFrame.AddError("Failed to set this ruleset as current:" + e1.getMessage(), new JFrame());
				} catch (FirewallException e1) {
					ErrorFrame.AddError("Failed to set this ruleset as current:"+ e1.getMessage(), new JFrame());
				} catch (ReadWriteException e1) {
					ErrorFrame.AddError("Failed to set this ruleset as current:"+ e1.getMessage(), new JFrame());
				}
				
			}	  
		});

		buttons.add(set);
		
		
		return buttons;	
	}

	/**
	 * Adds buttons for adding, deleting, editing rule
	 */
	protected Box getDownRulesButtons()
	{		
		/* Button for adding */	
		Box buttons = Box.createVerticalBox();
	
		JButton add = new JButton("Add Rule             ");
		add.setToolTipText("Add the new rule to the ruleset");
		
		buttons.add(add);
		add.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				JFrame frame = new RuleAddFrame(UI);
				frame.setVisible(true);
			}	  
		});
		
		/* Button for deleting */
	
		JButton delete = new JButton("Delete Rule         ");
		delete.setToolTipText("Delete the selected rule");
		
		buttons.add(delete);		
		delete.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				try {
					int[] inSelectedRows = RulesAdvancedTable.currentInRulesAdvancedTable.getSelectedRows();
					int[] outSelectedRows = RulesAdvancedTable.currentOutRulesAdvancedTable.getSelectedRows();
					
					/* delete the selected in tables rule in ruleset, update windows */
					if((inSelectedRows.length == 0) && (outSelectedRows.length == 0))
					{
				    	ErrorFrame.AddError("You need to select rule to delete in table", 
				    						 RulesAdvancedFrame.currentRulesAdvancedFrame);				
				    	return;
					}
					for(int i = 0; i < inSelectedRows.length; i++)
					{
						int id = RulesAdvancedTable.currentInRulesAdvancedTable.getRuleId(i);
						if(id != -1)
						{
								UI.deleteRule(RulesTableType.IN, Settings.ruleset, id+1);
						}
					}
					
					for(int i = 0; i < outSelectedRows.length; i++)
					{
						int id = RulesAdvancedTable.currentOutRulesAdvancedTable.getRuleId(i);						
						
						if(id != -1)
						{
								UI.deleteRule(RulesTableType.OUT, Settings.ruleset, id+1);
						}
					}
					
					
					RulesAdvancedTable.currentInRulesAdvancedTable.build();
					RulesAdvancedTable.currentOutRulesAdvancedTable.build();
				}  catch (RemoteException e1) {
					ErrorFrame.AddError("Failed to delete the rule:" + e1.getMessage(), new JFrame());
				} catch (FirewallException e1) {
					ErrorFrame.AddError("Failed to delete the rule:" + e1.getMessage(), new JFrame());
				} catch (ReadWriteException e1) {
					ErrorFrame.AddError("Failed to delete the rule:" + e1.getMessage(), new JFrame());
				} catch (NotExpertException e1) {
					ErrorFrame.AddError("Failed to delete the rule:" + e1.getMessage(), new JFrame());
				}
			}	  
		});
		
		/* Button for reseting */
	
		JButton edit = new JButton("Edit Rule             ");
		edit.setToolTipText("Edit the selected rule");

		buttons.add(edit);
		edit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				int[] inSelectedRows = RulesAdvancedTable.currentInRulesAdvancedTable.getSelectedRows();
				int[] outSelectedRows = RulesAdvancedTable.currentOutRulesAdvancedTable.getSelectedRows();
				
				
				/* delete the selected in tables rule in ruleset, update windows */
				if((inSelectedRows.length + outSelectedRows.length != 1))
				{
			    	ErrorFrame.AddError("You need to select one rule to edit in table", 
			    						 RulesAdvancedFrame.currentRulesAdvancedFrame);
			    	return;
				}
				
				/* Parameters for rule */
				String[] rule = new String[RulesAdvancedTable.columnNames.length];
				RulesTableType type = null;
				
				/* Selected row index */
				int index = 0;
				
				/* Take the relevant row */
				if(inSelectedRows.length == 1)
				{
					type = RulesTableType.IN;
					index = inSelectedRows[0];
					for(int i = 0; i < rule.length; i++)
					{
						rule[i] = (String) RulesAdvancedTable.currentInRulesAdvancedTable.getValueAt(index, i);
					}
				}
				else /* outSelectedRows.length == 1 */
				{
					type = RulesTableType.OUT;
					index = outSelectedRows[0];
					for(int i = 0; i < rule.length; i++)
					{
						rule[i] = (String) RulesAdvancedTable.currentOutRulesAdvancedTable.getValueAt(index, i);
					}					
				}
				
				/* Show frame */
				JFrame frame = new RuleEditFrame(rule, type, UI);
				frame.setVisible(true);
			}	  
		});
		
		return buttons;	
	}
	
	/**
	 * @param table in/out type
	 * @return table of rules
	 */
	protected AbstractRulesTable getTable(RulesTableType type)
	{
		return new RulesAdvancedTable(type, UI);
	}
	
	
	/**
	 * Action on changing the table. Table displays current/not current FW ruleset.
	 */
	public void isCurrentRuleSet(boolean isCurrent)
	{
		if (isCurrent ){
			setTitle(title);
		}
		else{
			setTitle(title + " * ");
		}
	}

}
